package com.sean.reverse.controller;

import com.sean.reverse.exception.CookieErrorException;
import com.sean.reverse.exception.HandleException;
import com.sean.reverse.exception.ThreadExistException;
import com.sean.reverse.service.ReverseService;
import com.sean.reverse.util.IPHelper;
import com.sean.reverse.util.Result;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author sean
 * @createTime 2022/4/11 22:41
 * @description
 */
@Slf4j
@RestController
@RequestMapping("/reverse")
public class ReverseController {

    @Resource
    ReverseService reverseService;
    @Resource
    ThreadPoolTaskScheduler threadPoolTaskScheduler;
    @Resource
    HandleException handleException;

    @GetMapping("badminton")
    @Operation(summary = "预约明天的场地，一个或两个时间段。time格式：8-9, 9-10, 10-11, ……, 21-22")
    public Result reverseBadminton(HttpServletRequest request,
                             @RequestParam("court") String court,
                             @RequestParam("cookie") String cookie,
                             @RequestParam("time-slot1") String timeSlot1,
                             @RequestParam(value = "time-slot2", required = false) String timeSlot2,
                             @RequestParam(value = "phone", required = false) String phone) throws ParseException {
        log.info(IPHelper.getIpAddress(request) + "请求了预约场地:oneTime"
                + " cookie:"+cookie + " time-slot1:"+timeSlot1 + " time-slot2:"+timeSlot2 + " phone:"+phone);
        SimpleDateFormat sdfTime = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
        SimpleDateFormat sdfDay = new SimpleDateFormat("yyyyMMdd");

        long todayTime = new Date().getTime();
        String today = sdfDay.format(todayTime);
        long time = sdfTime.parse(today + " 10:00:00").getTime();

        String tomorrow;
        if(todayTime > time){//超过了今天的十点，定时在明天抢，抢后天的场地
            tomorrow = sdfDay.format(todayTime + 1000*60*60*24);
//            tomorrow = today;
        }else{//没有过今天的十点，在今天抢，抢明天的场地
            tomorrow = today;
        }
        //启动一个线程定时抢
        threadPoolTaskScheduler.schedule(new Runnable() {
            @Override
            public void run() {
                String name = timeSlot1 + (StringUtils.isEmpty(timeSlot2) ? "" : " "+timeSlot2);
                Thread sameNameThread = null;
                synchronized (this){
                    //判断如果已经存在相同的线程
                    ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
                    Thread[] threads = new Thread[Thread.activeCount()];
                    threadGroup.enumerate(threads);
                    for (Thread t:threads){
//                    System.out.println(t.getName());
                        if(t.getName().contains(name)){
                            sameNameThread = t;
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            break;
                        }
                    }
                    if(sameNameThread != null && sameNameThread.getName().contains(name)){
                        handleException.handleThreadExistException(new ThreadExistException("已经存在相同的定时抢线程"));
                        return;
                    }
                    //设置线程名字
                    String preName = Thread.currentThread().getName();
                    Thread.currentThread().setName(preName + ":" + name);
                }

                System.out.println("时间" + sdfTime.format(new Date()) + "：线程运行，开抢……");
                String courtName = reverseService.reverse(court, cookie, timeSlot1, timeSlot2, true, phone);
                if(courtName.equals("预约失败：Cookie失效")){
                    handleException.handleCookieErrorException(new CookieErrorException("Cookie失效"));
                    //修改线程名字，防止已经执行过的核心线程不会被清除，手动修改线程名
                    Thread.currentThread().setName(Thread.currentThread().getName().replace(name, ""));
                    return;
                }
                //没抢到的话，再抢几次
                int i = 0, sum = 5;
                while(courtName.equals("预约失败") && i<sum){
                    System.out.println("第" + (i+1) + "次：");
                    courtName = reverseService.reverse(court, cookie, timeSlot1, timeSlot2, true, phone);
                    i++;
                }
                //修改线程名字，防止已经执行过的核心线程不会被清除，手动修改线程名
                Thread.currentThread().setName(Thread.currentThread().getName().replace(name, ""));
            }
        }, sdfTime.parse(tomorrow + " 09:59:59"));

        return Result.success("已经开启定时抢");
    }

    @GetMapping("badmintonToday")
    @Operation(summary = "预约今天的场地，一个或两个时间段。time格式：8-9, 9-10, 10-11, …, 21-22")
    public Result reverseBadmintonOnToday(HttpServletRequest request,
                                  @RequestParam("court") String court,
                                  @RequestParam("cookie") String cookie,
                                  @RequestParam("time-slot1") String timeSlot1,
                                  @RequestParam(value = "time-slot2", required = false) String timeSlot2,
                                  @RequestParam(value = "phone", required = false) String phone){
        log.info(IPHelper.getIpAddress(request) + "请求了预约场地:oneTimeToday"
                + " cookie:"+cookie + " time-slot1:"+timeSlot1 + " time-slot2:"+timeSlot2 + " phone:"+phone);
        String courtName = reverseService.reverse(court, cookie, timeSlot1, timeSlot2, false, phone);
        return Result.success(courtName);
    }

    @GetMapping("hello")
    @Operation(summary = "测试Hello")
    public Result hello(HttpServletRequest request){
        log.info(IPHelper.getIpAddress(request) + "请求了Hello");
        return Result.success("Hello, 成功了！");
    }
}
